home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) __author__ = 'Robert Ancell <bob27@users.sourceforge.net>' __license__ = 'GNU General Public License Version 2' __copyright__ = 'Copyright 2005-2006 Robert Ancell' __all__ = [ 'GtkUI'] import os import sys import time from gettext import gettext as _ import gobject import gtk import gtk.glade as gtk import gtk.gdk as gtk import cairo import pango from glchess.defaults import * import LaunchpadIntegration os.environ['PYGTK_FATAL_EXCEPTIONS'] = '1' import glchess.config as glchess import glchess.ui as glchess import glchess.chess.board as glchess import dialogs import log import chessview import network gtk.window_set_default_icon_name(ICON_NAME) def loadGladeFile(name, root = None): return gtk.glade.XML(os.path.join(GLADE_DIR, name), root, domain = DOMAIN) class GLibTimer(glchess.ui.Timer): ''' ''' def __init__(self, ui, feedback, duration): self.ui = ui self.feedback = feedback self.tickTime = 0 self.reportedTickTime = 0 self.timer = None self.tickTimer = None self.startTime = None self.set(duration * 1000) def set(self, duration): ''' ''' if self.timer is not None: gobject.source_remove(self.timer) if self.tickTimer is not None: gobject.source_remove(self.tickTimer) self.duration = duration self.consumed = 0 def __consumed(self, now): if self.startTime is None: return self.consumed return self.consumed + (now - self.startTime) def getRemaining(self): '''Extends ui.Timer''' return self.duration - self._GLibTimer__consumed(int(1000 * time.time())) def pause(self): '''Extends ui.Timer''' if self.timer is None: return None self.consumed = self._GLibTimer__consumed(int(1000 * time.time())) gobject.source_remove(self.timer) if self.tickTimer is not None: gobject.source_remove(self.tickTimer) self.timer = None self.tickTimer = None def run(self): '''Extends ui.Timer''' if self.timer is not None: return None self.startTime = int(1000 * time.time()) self.timer = gobject.timeout_add(self.duration - self.consumed, self._GLibTimer__expired) self._GLibTimer__setSecondTimer(self.startTime) def __setSecondTimer(self, now): '''Set a timer to expire on the next second boundary''' if not self.tickTimer is None: raise AssertionError consumed = self._GLibTimer__consumed(now) t = 1000 * (consumed / 1000 + 1) if t <= self.reportedTickTime: self.tickTime = self.reportedTickTime + 1000 else: self.tickTime = t if self.tickTime > self.duration: self.tickTimer = None else: self.tickTimer = gobject.timeout_add(self.tickTime - consumed, self._GLibTimer__tick) def __expired(self): '''Called by GLib main loop''' self.feedback.onTick(0) self.feedback.onExpired() if self.tickTimer is not None: gobject.source_remove(self.tickTimer) self.timer = None self.tickTimer = None return False def __tick(self): '''Called by GLib main loop''' self.reportedTickTime = self.tickTime self.feedback.onTick((self.duration - self.tickTime) / 1000) self.tickTimer = None self._GLibTimer__setSecondTimer(int(1000 * time.time())) return False def delete(self): '''Extends ui.Timer''' gobject.source_remove(self.timer) class GtkUI(glchess.ui.UI): ''' ''' _gui = None __lastTime = None __animationTimer = None __playerModel = None __aboutDialog = None __saveGameDialogs = None __renderGL = False openGLInfoPrinted = False __joinGameDialogs = None __networkGames = None __defaultWhiteAI = None __defaultBlackAI = None __attentionCounter = 0 whiteTimeString = '\xe2\x88\x9e' blackTimeString = '\xe2\x88\x9e' width = None height = None isFullscreen = False isMaximised = False view = None def __init__(self, feedback): '''Constructor for a GTK+ glChess GUI''' self.feedback = feedback self._watches = { } self._GtkUI__networkGames = { } self.newGameDialog = None self.loadGameDialog = None self._GtkUI__saveGameDialogs = { } self._GtkUI__joinGameDialogs = [] tooltip = gtk.Tooltips() tooltip.force_window() if hasattr(tooltip, 'tip_window') and tooltip.tip_window != None: tooltip.tip_window.ensure_style() self._tooltipStyle = tooltip.tip_window.get_style() else: self._tooltipStyle = None self._tooltipWidgetsDrawn = { } self._gui = loadGladeFile('glchess.glade') self._gui.signal_autoconnect(self) self.mainWindow = self._gui.get_widget('glchess_app') self._GtkUI__getWidget('toolbar').unset_style() self._GtkUI__playerModel = gtk.ListStore(str, str, str) iter = self._GtkUI__playerModel.append() self._GtkUI__playerModel.set(iter, 0, '', 1, 'stock_person', 2, _('Human')) self._GtkUI__logWindow = log.LogWindow(self._gui.get_widget('log_notebook')) self.preferences = dialogs.GtkPreferencesDialog(self) group = gtk.SizeGroup(gtk.SIZE_GROUP_BOTH) group.add_widget(self._GtkUI__getWidget('left_nav_box')) group.add_widget(self._GtkUI__getWidget('right_nav_box')) combo = self._GtkUI__getWidget('history_combo') cell = gtk.CellRendererText() combo.pack_start(cell, False) combo.add_attribute(cell, 'text', 2) widget = self._gui.get_widget('help2_menu') LaunchpadIntegration.set_sourcepackagename('gnome-games') LaunchpadIntegration.add_items(widget, 1, True, False) self._updateViewButtons() for key in [ 'show_toolbar', 'show_history', 'fullscreen', 'show_3d', 'show_3d_smooth', 'show_comments', 'show_numbering', 'show_move_hints', 'width', 'height', 'move_format', 'promotion_type', 'board_view', 'enable_networking']: glchess.config.watch(key, self._GtkUI__applyConfig) def setTooltipStyle(self, widget): """Set a widget to be in the tooltip style. 'widget' is the widget to modify. """ if self._tooltipStyle is None: return None widget.set_style(self._tooltipStyle) widget.connect('expose_event', self._on_tooltip_expose_event) widget.queue_draw() def _on_tooltip_expose_event(self, widget, event): '''Gtk+ callback''' allocation = widget.allocation widget.style.paint_flat_box(widget.window, gtk.STATE_NORMAL, gtk.SHADOW_OUT, None, widget, 'tooltip', allocation.x, allocation.y, allocation.width, allocation.height) if not self._tooltipWidgetsDrawn.has_key(widget): self._tooltipWidgetsDrawn[widget] = True widget.queue_draw() def watchFileDescriptor(self, fd): '''Extends ui.UI''' self._watches[fd] = gobject.io_add_watch(fd, gobject.IO_IN | gobject.IO_PRI | gobject.IO_HUP | gobject.IO_ERR, self._GtkUI__readData) def unwatchFileDescriptor(self, fd): '''Extends ui.UI''' gobject.source_remove(self._watches.pop(fd)) def writeFileDescriptor(self, fd): '''Extends ui.UI''' gobject.io_add_watch(fd, gobject.IO_OUT, self._GtkUI__writeData) def addTimer(self, feedback, duration): '''Extends ui.UI''' return GLibTimer(self, feedback, duration) def __timerExpired(self, method): method() return True def __readData(self, fd, condition): return self.feedback.onReadFileDescriptor(fd) def __writeData(self, fd, condition): return self.feedback.onWriteFileDescriptor(fd) def addAIEngine(self, name): """Register an AI engine. 'name' is the name of the engine. TODO: difficulty etc etc """ iter = self._GtkUI__playerModel.append() self._GtkUI__playerModel.set(iter, 0, name, 1, 'stock_notebook', 2, name) if self._GtkUI__defaultBlackAI is None: self._GtkUI__defaultBlackAI = name def setView(self, title, feedback, isPlayable = True): '''Extends ui.UI''' moveFormat = glchess.config.get('move_format') showComments = glchess.config.get('show_comments') self.view = chessview.GtkView(self, feedback, moveFormat = moveFormat, showComments = showComments) self.view.setTitle(title) self.view.isPlayable = isPlayable self.view.viewWidget.setRenderGL(self._GtkUI__renderGL) viewport = self._GtkUI__getWidget('game_viewport') child = viewport.get_child() if child is not None: viewport.remove(child) viewport.add(self.view.widget) self._updateViewButtons() if self.view is not None: self.setTimers(self.view.whiteTime, self.view.blackTime) return self.view def updateTitle(self): ''' ''' if self.view is not None and len(self.view.title) > 0: if self.view.needsSaving: title = _('Chess - *%(game_name)s') % { 'game_name': self.view.title } else: title = _('Chess - %(game_name)s') % { 'game_name': self.view.title } else: title = _('Chess') self.mainWindow.set_title(title) def addLogWindow(self, title, executable, description): ''' ''' return self._GtkUI__logWindow.addView(title, executable, description) def setTimers(self, whiteTime, blackTime): ''' ''' unlimitedTimeText = _('\xe2\x88\x9e') if whiteTime is None: whiteString = unlimitedTimeText else: t = whiteTime[1] whiteString = '%i:%02i' % (t / 60, t % 60) if blackTime is None: blackString = unlimitedTimeText else: t = blackTime[1] blackString = '%i:%02i' % (t / 60, t % 60) if whiteString != self.whiteTimeString: self.whiteTimeString = whiteString self._gui.get_widget('white_time_label').queue_draw() if blackString != self.blackTimeString: self.blackTimeString = blackString self._gui.get_widget('black_time_label').queue_draw() def run(self): '''Run the UI. This method will not return. ''' for name in [ 'show_toolbar', 'show_history', 'show_3d', 'show_3d_smooth', 'show_comments', 'show_numbering', 'show_move_hints', 'move_format', 'promotion_type', 'board_view', 'maximised', 'enable_networking']: try: value = glchess.config.get(name) except glchess.config.Error: continue self._GtkUI__applyConfig(name, value) self._GtkUI__resize() self.mainWindow.show() self._GtkUI__applyConfig('fullscreen', glchess.config.get('fullscreen')) gtk.main() def reportGameLoaded(self, game): '''Extends glchess.ui.UI''' dialogs.GtkNewGameDialog(self, self._GtkUI__playerModel, game) def addNetworkDialog(self, feedback): '''Extends glchess.ui.UI''' self._GtkUI__networkDialog = network.GtkNetworkGameDialog(self, feedback) return self._GtkUI__networkDialog def addNetworkGame(self, name, game): '''Extends glchess.ui.UI''' self._GtkUI__networkDialog.addNetworkGame(name, game) def removeNetworkGame(self, game): '''Extends glchess.ui.UI''' self._GtkUI__networkDialog.removeNetworkGame(game) def requestSave(self, title): '''Extends glchess.ui.UI''' dialog = gtk.MessageDialog(flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, type = gtk.MESSAGE_WARNING, message_format = title) dialog.format_secondary_text(_("If you don't save the changes to this game will be permanently lost")) dialog.add_button(_('Close _without saving'), gtk.RESPONSE_OK) dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT) dialog.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT) response = dialog.run() dialog.destroy() if response == gtk.RESPONSE_ACCEPT: return glchess.ui.SAVE_YES if response == gtk.RESPONSE_OK: return glchess.ui.SAVE_NO return glchess.ui.SAVE_ABORT def close(self): '''Extends glchess.ui.UI''' if self.width is not None: glchess.config.set('width', self.width) if self.height is not None: glchess.config.set('height', self.height) def _incAttentionCounter(self, offset): ''' ''' self._GtkUI__attentionCounter += offset self._GtkUI__updateAttention() def __updateAttention(self): ''' ''' widget = self.mainWindow if self._GtkUI__attentionCounter != 0: pass widget.set_urgency_hint(not widget.is_active()) def _on_focus_changed(self, widget, event): '''Gtk+ callback''' self._GtkUI__updateAttention() def _saveView(self, view, path): ''' ''' if path is None: error = None else: error = view.feedback.save(path) if error is not None: return error self._GtkUI__saveGameDialogs.pop(view) def __resize(self): try: width = glchess.config.get('width') height = glchess.config.get('height') except glchess.config.Error: return None self.mainWindow.resize(width, height) def __applyConfig(self, name, value): ''' ''' if name == 'width' or name == 'height': self._GtkUI__resize() return None if name == 'show_toolbar': toolbar = self._GtkUI__getWidget('toolbar') if value is True: toolbar.show() else: toolbar.hide() elif name == 'enable_networking': menuItem = self._GtkUI__getWidget('menu_play_online_item') toolbarButton = self._GtkUI__getWidget('play_online_button') if value is True: menuItem.show() toolbarButton.show() else: menuItem.hide() toolbarButton.hide() elif name == 'show_history': box = self._GtkUI__getWidget('navigation_box') if value is True: box.show() else: box.hide() elif name == 'maximised': window = self.mainWindow if value is True: window.maximize() else: window.unmaximize() elif name == 'fullscreen': window = self.mainWindow if value is True: window.fullscreen() else: window.unfullscreen() elif name == 'show_3d': if value and not (chessview.haveGLSupport): title = _('Unable to enable 3D mode') errors = '\n'.join(chessview.openGLErrors) description = _('You are unable to play in 3D mode due to the following problems:\n%(errors)s\n\nPlease contact your system administrator to resolve these problems, until then you will be able to play chess in 2D mode.') % { 'errors': errors } dialog = gtk.MessageDialog(type = gtk.MESSAGE_WARNING, message_format = title) dialog.format_secondary_text(description) dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) dialog.run() dialog.destroy() glchess.config.set('show_3d', False) value = False self._GtkUI__renderGL = value self._GtkUI__getWidget('menu_view_3d').set_active(value) self.view.viewWidget.setRenderGL(value) elif name == 'show_3d_smooth': if not chessview.haveGLAccumSupport: value = False self.view.feedback.showSmooth(value) elif name == 'show_comments': self.view.setShowComments(value) elif name == 'show_move_hints': self.view.feedback.showMoveHints(value) elif name == 'show_numbering': self.view.feedback.showBoardNumbering(value) elif name == 'move_format': self.view.setMoveFormat(value) elif name == 'promotion_type': pass elif name == 'board_view': pass elif not False: raise AssertionError, 'Unknown config item: %s' % name def startAnimation(self): '''Start the animation callback''' if self._GtkUI__animationTimer is None: self._GtkUI__lastTime = time.time() self._GtkUI__animationTimer = gobject.timeout_add(10, self._GtkUI__animate) def __animate(self): now = time.time() step = now - self._GtkUI__lastTime if step < 0: step = 0 elif step > 1: step = 1 self._GtkUI__lastTime = now animating = self.feedback.onAnimate(step) if not animating: self._GtkUI__animationTimer = None return animating def __getWidget(self, name): widget = self._gui.get_widget(name) if not widget is not None: raise AssertionError, 'Unable to find widget: %s' % name return widget def _on_white_time_paint(self, widget, event): '''Gtk+ callback''' self._GtkUI__drawTime(self.whiteTimeString, widget, (0, 0, 0), (1, 1, 1)) def _on_black_time_paint(self, widget, event): '''Gtk+ callback''' self._GtkUI__drawTime(self.blackTimeString, widget, (1, 1, 1), (0, 0, 0)) def __drawTime(self, text, widget, fg, bg): ''' ''' if widget.state == gtk.STATE_INSENSITIVE: alpha = 0.5 else: alpha = 1 context = widget.window.cairo_create() context.set_source_rgba(bg[0], bg[1], bg[2], alpha) context.paint() (_, _, w, h) = widget.get_allocation() context.set_source_rgba(fg[0], fg[1], fg[2], alpha) context.select_font_face('fixed', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) context.set_font_size(0.6 * h) (x_bearing, y_bearing, width, height, _, _) = context.text_extents(text) context.move_to((w - width) / 2 - x_bearing, (h - height) / 2 - y_bearing) context.show_text(text) widget.set_size_request(int(width) + 6, -1) def _on_toggle_3d_clicked(self, widget): '''Gtk+ callback''' if widget.get_active(): value = True else: value = False glchess.config.set('show_3d', value) def _on_show_logs_clicked(self, widget): '''Gtk+ callback''' window = self._gui.get_widget('log_window') if widget.get_active(): window.present() else: window.hide() def _on_history_combo_changed(self, widget): '''Gtk+ callback''' model = widget.get_model() iter = widget.get_active_iter() if iter is None: return None moveNumber = model.get_value(iter, 1) if moveNumber == len(model) - 1: moveNumber = -1 haveMoves = len(model) > 1 for widget in ('first_move_button', 'prev_move_button'): if haveMoves: pass self._GtkUI__getWidget(widget).set_sensitive(moveNumber != 0) for widget in ('last_move_button', 'next_move_button'): if haveMoves: pass self._GtkUI__getWidget(widget).set_sensitive(moveNumber != -1) self.view._setMoveNumber(moveNumber) def __selectMoveNumber(self, moveNumber): '''FIXME ''' combo = self._GtkUI__getWidget('history_combo') maxNumber = len(combo.get_model()) if moveNumber < 0: moveNumber = maxNumber + moveNumber if moveNumber < 0: moveNumber = 0 if moveNumber >= maxNumber: moveNumber = maxNumber - 1 combo.set_active(moveNumber) def __selectMoveNumberRelative(self, offset): '''FIXME ''' combo = self._GtkUI__getWidget('history_combo') selected = combo.get_active() maxNumber = len(combo.get_model()) new = selected + offset if new < 0: new = 0 elif new >= maxNumber: new = maxNumber - 1 self._GtkUI__selectMoveNumber(new) def _on_history_start_clicked(self, widget): '''Gtk+ callback''' self._GtkUI__selectMoveNumber(0) def _on_history_previous_clicked(self, widget): '''Gtk+ callback''' self._GtkUI__selectMoveNumberRelative(-1) def _on_history_next_clicked(self, widget): '''Gtk+ callback''' self._GtkUI__selectMoveNumberRelative(1) def _on_history_latest_clicked(self, widget): '''Gtk+ callback''' self._GtkUI__selectMoveNumber(-1) def _updateViewButtons(self): ''' ''' if self.view is not None: pass enable = self.view.isPlayable for widget in ('save_game_button', 'menu_save_item', 'menu_save_as_item'): self._GtkUI__getWidget(widget).set_sensitive(enable) combo = self._GtkUI__getWidget('history_combo') if self.view is None: if combo.get_model() != None: combo.set_model(None) else: (model, selected) = self.view._getModel() combo.set_model(model) if selected < 0: selected = len(model) + selected combo.set_active(selected) self._GtkUI__getWidget('navigation_box').set_sensitive(enable) if enable: pass enable = self.view.gameResult is None def _on_new_game_button_clicked(self, widget): '''Gtk+ callback''' if self.newGameDialog: self.newGameDialog.window.present() else: self.newGameDialog = dialogs.GtkNewGameDialog(self, self._GtkUI__playerModel) def _on_join_game_button_clicked(self, widget): '''Gtk+ callback''' self.feedback.onNewNetworkGame() def _on_open_game_button_clicked(self, widget): '''Gtk+ callback''' if self.loadGameDialog: self.loadGameDialog.window.present() else: self.loadGameDialog = dialogs.GtkLoadGameDialog(self) def _on_save_game_button_clicked(self, widget): '''Gtk+ callback''' if self.view.feedback.getFileName() is not None: self.view.feedback.save() return None try: dialog = self._GtkUI__saveGameDialogs[self.view] except KeyError: self.view.feedback.getFileName() is not None self.view.feedback.getFileName() is not None dialog = self._GtkUI__saveGameDialogs[self.view] = dialogs.GtkSaveGameDialog(self, self.view) except: self.view.feedback.getFileName() is not None dialog.window.present() def _on_save_as_game_button_clicked(self, widget): '''Gtk+ callback''' try: dialog = self._GtkUI__saveGameDialogs[self.view] except KeyError: dialog = self._GtkUI__saveGameDialogs[self.view] = dialogs.GtkSaveGameDialog(self, self.view, self.view.feedback.getFileName()) dialog.window.present() def _on_undo_move_clicked(self, widget): '''Gtk+ callback''' self.view.feedback.undo() def _on_resign_clicked(self, widget): '''Gtk+ callback''' self.view.feedback.resign() def _on_claim_draw_clicked(self, widget): '''Gtk+ callback''' if self.view.feedback.claimDraw(): return None title = _('Unable to claim draw') message = _('You may claim a draw when:\na) The board has been in the same state three times (Three fold repetition)\nb) Fifty moves have occured where no pawn has moved and no piece has been captured (50 move rule)') dialog = gtk.MessageDialog(flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, type = gtk.MESSAGE_WARNING, message_format = title) dialog.format_secondary_text(message) dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_ACCEPT) dialog.run() dialog.destroy() def _on_preferences_clicked(self, widget): '''Gtk+ callback''' self.preferences.setVisible(True) def _on_help_clicked(self, widget): '''Gtk+ callback''' try: gtk.show_uri(self.mainWindow.get_screen(), 'ghelp:glchess', gtk.get_current_event_time()) except gobject.GError: e = None print _('Unable to display help: %s') % str(e) def _on_view_fullscreen_clicked(self, widget): '''Gtk+ callback''' glchess.config.set('fullscreen', True) def _on_view_unfullscreen_clicked(self, widget): '''Gtk+ callback''' glchess.config.set('fullscreen', False) def _on_3d_support_dialog_delete_event(self, widget, event): '''Gtk+ callback''' return True def _on_3d_support_dialog_response(self, widget, responseId): '''Gtk+ callback''' if self._GtkUI__aboutDialog is not None: return None widget.hide() return False def _on_about_clicked(self, widget): '''Gtk+ callback''' if self._GtkUI__aboutDialog is not None: return None dialog.set_transient_for(self.mainWindow) dialog.set_name(APPNAME) dialog.set_version(VERSION) dialog.set_copyright(COPYRIGHT) dialog.set_license(LICENSE[0] + '\n\n' + LICENSE[1] + '\n\n' + LICENSE[2]) dialog.set_wrap_license(True) dialog.set_comments(DESCRIPTION) dialog.set_authors(AUTHORS) dialog.set_artists(ARTISTS) dialog.set_translator_credits(_('translator-credits')) dialog.set_website(WEBSITE) dialog.set_website_label(WEBSITE_LABEL) dialog.set_logo_icon_name(ICON_NAME) dialog.connect('response', self._on_glchess_about_dialog_close) dialog.show() def _on_glchess_about_dialog_close(self, widget, event): '''Gtk+ callback''' self._GtkUI__aboutDialog.destroy() self._GtkUI__aboutDialog = None return False def _on_log_window_delete_event(self, widget, event): '''Gtk+ callback''' self._gui.get_widget('menu_view_logs').set_active(False) return True def _on_resize(self, widget, event): '''Gtk+ callback''' if self.isMaximised or self.isFullscreen: return None self.width = event.width self.height = event.height def _on_window_state_changed(self, widget, event): '''Gtk+ callback''' if event.changed_mask & gtk.gdk.WINDOW_STATE_MAXIMIZED: self.isMaximised = event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED != 0 glchess.config.set('maximised', self.isMaximised) if event.changed_mask & gtk.gdk.WINDOW_STATE_FULLSCREEN: self.isFullscreen = event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN != 0 if self.isFullscreen: self._gui.get_widget('menu_fullscreen').hide() self._gui.get_widget('menu_leave_fullscreen').show() else: self._gui.get_widget('menu_leave_fullscreen').hide() self._gui.get_widget('menu_fullscreen').show() def _on_close_window(self, widget, event): '''Gtk+ callback''' self.feedback.onQuit() return True def _on_menu_quit(self, widget): '''Gtk+ callback''' self.feedback.onQuit() if __name__ == '__main__': ui = GtkUI() ui.run()